#include <iostream>
#include <vector>
#include "myThread.hpp"
#include "LockGuard.hpp"

using namespace ThreadMoudle;

// 抢票
int tickets = 10000; // 票

//1.全局锁
// pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER; // 锁--全局/静态
// void *threadRun(std::string &name)
// {
//     //如果锁的初始化放在新线程运行函数这里，则每个线程每次运行锁的值都重置成了1，导致每个线程都能正常并发进入临界区
//     while (true)
//     {
//         pthread_mutex_lock(&gmutex); // 加锁
//         if (tickets > 0)
//         {
//             usleep(1000); // 单位 微秒
//             std::cout << name << " ticket " << tickets << std::endl;
//             tickets--;
//             pthread_mutex_unlock(&gmutex); // 解锁
//         }
//         else
//         {
//             pthread_mutex_unlock(&gmutex); // 解锁
//             break;
//         }
//     }
//     return (void *)111;
// }

//2.把锁到类数据里，传给新线程
// void threadRun(threadData *td)
// {
//     sleep(2);
//     // 如果锁的初始化放在新线程运行函数这里，则每个线程每次运行锁的值都重置成了1，导致每个线程都能正常并发进入临界区
//     while (true)
//     {
//         pthread_mutex_lock(td->_lock);
//         if (tickets > 0)
//         {
//             usleep(1000); // 单位 微秒
//             std::cout << td->_name << " ticket " << tickets << std::endl;
//             tickets--;
//             pthread_mutex_unlock(td->_lock);
//         }
//         else
//         {
//             pthread_mutex_unlock(td->_lock);
//             break;
//         }
//     }
// }

//3.用类封装的锁，每趟循环都会重新释放，创建
void threadRun(threadData *td)
{
    // 如果锁的初始化放在新线程运行函数这里，则每个线程每次运行锁的值都重置成了1，导致每个线程都能正常并发进入临界区
    while (true)
    {
        LockGuard ld(td->_lock);//用类封装的锁，每趟循环都会重新释放，创建
        if (tickets > 0)
        {
            usleep(1000); // 单位 微秒
            std::cout << td->_name << " ticket " << tickets << std::endl;
            tickets--;
        }
        else
        {
            break;
        }
    }
}


int main()
{
    pthread_mutex_t mutex;               // 创建锁
    pthread_mutex_init(&mutex, nullptr); // 线程库使用C写的，所以结构体传参都是用地址
    std::vector<myThread> mt;
    for (int i = 1; i <= 4; i++)
    {
        std::string name = "thread-" + std::to_string(i);
        threadData *td = new threadData(name, &mutex);
        //mt.push_back(myThread(name, threadRun, td));
        mt.push_back({name, threadRun, td});
    // mt.emplace_back(name, threadRun, td);//emplace_back 更加灵活，因为它在 vector 内部直接构造对象
        std::cout << name << std::endl;
        sleep(1);
    }

    // 运行
    //for (auto e: mt)//错；create 线程后的tid，在拷贝里，不在mt中成员里，给join的tid是未知的
    for (auto& e: mt)
    {
        e.Start();
    }
    // for (int i = 0; i < 4; i++)
    // {
    //     mt[i].Start();
    // }
    sleep(1);
    // 等待
    for (auto& e : mt)
    {
        e.Join();
    }

    pthread_mutex_destroy(&mutex); // 销毁锁

    return 0;
}

// void* threadRun(std::string& name)
// {
//     return (void*)111;
// }
// int main()
// {
//     std::string name = "thread-1";
//     myThread mythread(name, threadRun);
//     mythread.Start();//运行
//     std::cout << mythread.Name() << " " << mythread.Stat() << std::endl;
//     mythread.Stop();
//     mythread.Join();//等待

//     return 0;
// }